home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / libs / otm3d095 / 3dtools.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-14  |  25.9 KB  |  1,280 lines

  1. #include <dos.h>
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include "3dtools.h"
  6.  
  7. //      3dtools v0.95 - released 12-14-94
  8. //      C++ 3d engine
  9. //      coded by Voltaire/OTM
  10. //      all source Copyright (C) 1994 Zach Mortensen
  11. //
  12. //      compile using: wcl386 /mf /oneat /5r /d2 /c 3dtools.cpp
  13. //
  14. //      NOTE: for some STRANGE reason, a GP fault appears when the /d2
  15. //      switch is omitted, and disappears when it is used.  THIS MAKES
  16. //      DEBUGGING THE GPF VERY DIFFICULT!  IT IS NOT MY FAULT!  However, it
  17. //      is VERY annoying, because the /d2 switch disables many optimizations
  18. //      which would result in a significant speedup.
  19. //
  20. //      see 3DTOOLS.NFO and OTM-94.NFO for more information
  21.  
  22. world3d world;
  23. viewPoint camera;
  24. int matrix[9];
  25. int *perspect;
  26.  
  27. //////
  28.    //
  29.   //    dotProduct function definition
  30.  //
  31. //////
  32.  
  33.  
  34. int dotProduct(point3d *p1, point3d *p2)
  35. {
  36.     return((int) ((p1->rotoX * p2->rotoX) + (p1->rotoY * p2->rotoY) +
  37.     (p1->rotoZ * p2->rotoZ)));
  38. }
  39.  
  40. void initPerspect()
  41. {
  42.     int count;
  43.  
  44.     perspect = new int [32768];
  45.  
  46.     perspect[0] = 1024 * 64;
  47.  
  48.     for (count = 1; count < 32768; count++)
  49.         perspect[count] = 1024 * 64 / count;
  50. }
  51.  
  52. void delPerspect()
  53. {
  54.     delete perspect;
  55. }
  56.  
  57. //////
  58.    //
  59.   //    point3d class definitions
  60.  //
  61. //////
  62.  
  63.  
  64. point3d::point3d()
  65. {
  66. }
  67.  
  68. point3d::point3d(long x, long y, long z)
  69. {
  70.     setTo(x, y, z);
  71. }
  72.  
  73. void point3d::save(FILE *fp)
  74. {
  75.     int numWritten;
  76.  
  77.     pointRec *temp = new pointRec;
  78.  
  79.     temp->localX = localX;
  80.     temp->localY = localY;
  81.     temp->localZ = localZ;
  82.  
  83.     numWritten = fwrite(temp, sizeof(pointRec), 1, fp);
  84.  
  85. }
  86.  
  87. void point3d::load(FILE *fp)
  88. {
  89.     int numRead;
  90.  
  91.     pointRec *temp = new pointRec;
  92.  
  93.     numRead = fread(temp, sizeof(pointRec), 1, fp);
  94.  
  95.     localX = temp->localX;
  96.     localY = temp->localY;
  97.     localZ = temp->localZ;
  98.  
  99.     rotoX = localX;
  100.     rotoY = localY;
  101.     rotoZ = localZ;
  102. }
  103.  
  104. void point3d::setTo(long x, long y, long z)
  105. {
  106.     x3d = x;
  107.     y3d = y;
  108.     z3d = z;
  109.  
  110.     localX = x;
  111.     localY = y;
  112.     localZ = z;
  113.  
  114.     rotoX = x;
  115.     rotoY = y;
  116.     rotoZ = z;
  117.  
  118.     oX = 0;
  119.     oY = 0;
  120.     oZ = 0;
  121.  
  122.     xDeg = 0;
  123.     yDeg = 0;
  124.     zDeg = 0;
  125.  
  126.     // spherical schtuff
  127. /*
  128.     lRho = (long) sqrt(localX * localX + localY * localY + localZ * localZ);
  129.  
  130.     if (localZ == 0)
  131.     lTheta = (long) 180 * atan(localX) / PI;
  132.     else
  133.     lTheta = (long) 180 * atan(localX / localZ) / PI;
  134.  
  135.     if (lRho == 0)
  136.     lPhi = 0;
  137.     else
  138.     lPhi = (long) 180 * acos(localY / lRho) / PI;
  139.  
  140.     gRho = lRho;
  141.     gTheta = lTheta;
  142.     gPhi = lPhi;
  143. */
  144.     zeroNormal();
  145.  
  146.     xform2d();
  147. }
  148.  
  149. //      project the point to the screen
  150.  
  151. void point3d::xform2d()
  152. {
  153.  
  154.     if (z3d > 0)
  155.     {
  156.         x2d = ((x3d << 10) / z3d) + 159;
  157.         y2d = 99 - ((y3d << 10) / z3d);
  158.     }
  159.     else if (z3d == 0)
  160.     {
  161.         x2d = 159 + (x3d << 10);
  162.         y2d = 99 - (y3d << 10);
  163.     }
  164.     else
  165.     {
  166.         x2d = 159 - ((x3d << 10) / z3d);
  167.         y2d = 99 + ((y3d << 10) / z3d);
  168.     }
  169.  
  170.  
  171.     /*
  172.     if (z3d > 32767)
  173.     {
  174.         x2d = x3d * perspect[32767];
  175.         x2d = 159 + (x2d >> 6);
  176.  
  177.         y2d = y3d * perspect[32767];
  178.         y2d = 99 - (y2d >> 6);
  179.     }
  180.     else
  181.     {
  182.         x2d = x3d * perspect[z3d];
  183.         x2d = 159 + (x2d >> 6);
  184.  
  185.         y2d = y3d * perspect[z3d];
  186.         y2d = 99 - (y2d >> 6);
  187.     }
  188.      */
  189. }
  190.  
  191. void point3d::display(int color)
  192. {
  193.     setPixel((int) x2d, (int) y2d, color);
  194. }
  195.  
  196. //      set new origin coordinates
  197.  
  198. void point3d::setNewOrigin(point3d *p)
  199. {
  200.     oX = p->x3d;
  201.     oY = p->y3d;
  202.     oZ = p->z3d;
  203.  
  204.     localX = x3d - oX;
  205.     localY = y3d - oY;
  206.     localZ = z3d - oZ;
  207.  
  208.     rotoX = localX;
  209.     rotoY = localY;
  210.     rotoZ = localZ;
  211.  
  212. }
  213.  
  214. //      set new origin, retaining old local coordinates
  215.  
  216. void point3d::globalXform2origin(point3d *p)
  217. {
  218.     oX = p->x3d;
  219.     oY = p->y3d;
  220.     oZ = p->z3d;
  221.  
  222.     globalXform();
  223.     xform2d();
  224. /*
  225.     gRho = (long) sqrt(x3d * x3d + y3d * y3d + z3d * z3d);
  226.     if (z3d == 0)
  227.     gTheta = (long) 180 * atan(x3d) / PI;
  228.     else
  229.     gTheta = (long) 180 * atan(x3d / z3d) / PI;
  230.  
  231.     if (gRho == 0)
  232.     gPhi = 0;
  233.     else
  234.     gPhi = (long) 180 * acos(y3d / gRho) / PI;
  235. */
  236. }
  237.  
  238. //      copy origin coordinates from another point
  239.  
  240. void point3d::copyOrigin(point3d *p)
  241. {
  242.     oX = p->oX;
  243.     oY = p->oY;
  244.     oZ = p->oZ;
  245.  
  246.     globalXform();
  247.     xform2d();
  248. }
  249.  
  250. /*
  251. void point3d::localRotate(int dTheta, int dPhi)
  252. {
  253.  
  254.     lTheta += dTheta;
  255.     lPhi += dPhi;
  256.  
  257.     rotoX = (lRho * sin(lPhi * PI / 180) * cos(lTheta * PI / 180));
  258.     rotoY = (lRho * cos(lPhi * PI / 180));
  259.     rotoZ = (lRho * sin(lPhi * PI / 180) * sin(lTheta * PI / 180));
  260.  
  261.     globalXform();
  262.  
  263. }
  264. */
  265.  
  266. //      rotate a point about its origin (slow method)
  267.  
  268. void point3d::localRotate(int tX, int tY, int tZ)
  269. {
  270.     int cosX, sinX, cosY, sinY, cosZ, sinZ;
  271.  
  272.     xDeg += tX;
  273.     yDeg += tY;
  274.     zDeg += tZ;
  275.  
  276.     cosX = zDCos(xDeg);
  277.     sinX = zDSin(xDeg);
  278.     cosY = zDCos(yDeg);
  279.     sinY = zDSin(yDeg);
  280.     cosZ = zDCos(zDeg);
  281.     sinZ = zDSin(zDeg);
  282.  
  283.     // Z axis rotation first
  284.     i = (long) ((localX * cosZ - localY * sinZ) >> SINSHIFT);
  285.     j = (long) ((localX * sinZ + localY * cosZ) >> SINSHIFT);
  286.     k = (long) localZ;
  287.  
  288.     // now X axis rotation
  289.     rotoY = (long) ((j * cosX - k * sinX) >> SINSHIFT);
  290.     rotoZ = (long) ((j * sinX + k * cosX) >> SINSHIFT);
  291.     k = (long) rotoZ;
  292.  
  293.     // now Y axis
  294.     rotoX = (long) ((k * sinY + i * cosY) >> SINSHIFT);
  295.     rotoZ = (long) ((k * cosY - i * sinY) >> SINSHIFT);
  296.  
  297.     globalXform();
  298. }
  299.  
  300. //      rotate a point about its origin (faster method, *trig array
  301. //      used to store sin/cos data that remains constant for all
  302. //      points in a given object
  303.  
  304. void point3d::localRotate(int *trig)
  305. {
  306.     // Z axis rotation first
  307.     i = ((localX * trig[5] - localY * trig[4]) >> SINSHIFT);
  308.     j = ((localX * trig[4] + localY * trig[5]) >> SINSHIFT);
  309.     k = localZ;
  310.  
  311.     // now X axis rotation
  312.     rotoY = ((j * trig[1] - k * trig[0]) >> SINSHIFT);
  313.     rotoZ = ((j * trig[0] + k * trig[1]) >> SINSHIFT);
  314.     k = rotoZ;
  315.  
  316.     // now Y axis
  317.     rotoX = ((k * trig[2] + i * trig[3]) >> SINSHIFT);
  318.     rotoZ = ((k * trig[3] - i * trig[2]) >> SINSHIFT);
  319.  
  320.     globalXform();
  321.  
  322. }
  323.  
  324. //      rotate a point about THE (0, 0, 0) origin
  325.  
  326. void point3d::globalRotate(int *trig)
  327. {
  328.     // Z axis rotation first
  329.     i = (long) ((x3d * trig[5] - y3d * trig[4]) >> SINSHIFT);
  330.     j = (long) ((x3d * trig[4] + y3d * trig[5]) >> SINSHIFT);
  331.     k = (long) z3d;
  332.  
  333.     // now X axis rotation
  334.     y3d = (long) ((j * trig[1] - k * trig[0]) >> SINSHIFT);
  335.     z3d = (long) ((j * trig[0] + k * trig[1]) >> SINSHIFT);
  336.     k = (long) z3d;
  337.  
  338.     // now Y axis
  339.     x3d = (long) ((k * trig[2] + i * trig[3]) >> SINSHIFT);
  340.     z3d = (long) ((k * trig[3] - i * trig[2]) >> SINSHIFT);
  341.  
  342. }
  343.  
  344. //      translate (move) a point by (dX, dY, dZ)
  345.  
  346. void point3d::translate(long dX, long dY, long dZ)
  347. {
  348.     oX += dX;
  349.     oY += dY;
  350.     oZ += dZ;
  351.  
  352.     globalXform();
  353. }
  354.  
  355. //      transform local coordinates to global (world) coordinates
  356.  
  357. void point3d::globalXform()
  358. {
  359.     x3d = rotoX + oX;
  360.     y3d = rotoY + oY;
  361.     z3d = rotoZ + oZ;
  362. }
  363.  
  364. //      zero the normal for this point (used for gouraud shading)
  365.  
  366. void point3d::zeroNormal()
  367. {
  368.     nX = 0;
  369.     nY = 0;
  370.     nZ = 0;
  371.     nCount = 0;
  372. }
  373.  
  374. //      add (dX, dY, dZ) to the normal for this point
  375.  
  376. void point3d::addNormal(int dX, int dY, int dZ)
  377. {
  378.     nX += dX;
  379.     nY += dY;
  380.     nZ += dZ;
  381.     nCount ++;
  382. }
  383.  
  384. //      average the normal of this point
  385.  
  386. void point3d::avgNormal()
  387. {
  388.     long d;
  389.  
  390.     if (nCount)
  391.     {
  392.  
  393.         nX /= nCount;
  394.         nY /= nCount;
  395.         nZ /= nCount;
  396.  
  397.         d = (long) sqrt(nX * nX + nY * nY + nZ * nZ);
  398.  
  399.         nX = (256 * nX) / d;
  400.         nY = (256 * nY) / d;
  401.         nZ = (256 * nZ) / d;
  402.  
  403.     }
  404.  
  405. }
  406.  
  407. void point3d::matRotate()
  408. {
  409.     rotoX = (localX * matrix[0] + localY * matrix[1] + localZ * matrix[2]) >> SINSHIFT;
  410.     rotoY = (localX * matrix[3] + localY * matrix[4] + localZ * matrix[5]) >> SINSHIFT;
  411.     rotoZ = (localX * matrix[6] + localY * matrix[7] + localZ * matrix[8]) >> SINSHIFT;
  412.  
  413.     globalXform();
  414. }
  415.  
  416. point3d::~point3d()
  417. {
  418. }
  419.  
  420.  
  421. //////
  422.    //
  423.   //    line3d class definitions
  424.  //
  425. //////
  426.  
  427. //      NOTE - I don't really know why I included the line3d object,
  428. //      I never really use it anyway.  Most of it is undoubtedly full
  429. //      of bugs...
  430.  
  431. line3d::line3d(point3d *p1, point3d *p2, int c)
  432. {
  433.     point1 = p1;
  434.     point2 = p2;
  435.     calcVectors();
  436.     color = c;
  437.     flag = 0;
  438. }
  439.  
  440. line3d::line3d(long x1, long y1, long z1, long x2, long y2, long z2, int c)
  441. {
  442.     point1 = new point3d(x1, y1, z1);
  443.     point2 = new point3d(x2, y2, z2);
  444.     calcVectors();
  445.     color = c;
  446.     flag = 1;
  447. }
  448.  
  449. void line3d::draw()
  450. {
  451.     // draw_line(point1->x2d, point1->y2d, point2->x2d, point2->y2d, color);
  452. }
  453.  
  454. void line3d::calcVectors()
  455. {
  456.     i = (point1->x3d - point2->x3d);
  457.     j = (point1->y3d - point2->y3d);
  458.     k = (point1->z3d - point2->z3d);
  459. }
  460.  
  461. long line3d::xOfT(double t)
  462. {
  463.     return((long) (point1->x3d + (t * i)));
  464. }
  465.  
  466. long line3d::yOfT(double t)
  467. {
  468.     return((long) (point1->y3d + (t * j)));
  469. }
  470.  
  471. long line3d::zOfT(double t)
  472. {
  473.     return((long) (point1->z3d + (t * k)));
  474. }
  475.  
  476. double line3d::tOfX(long x)
  477. {
  478.     return((i == 0 ? 0 : (x - point1->x3d) / i));
  479. }
  480.  
  481. double line3d::tOfY(long y)
  482. {
  483.     return((j == 0 ? 0 : (y - point1->y3d) / j));
  484. }
  485.  
  486. double line3d::tOfZ(long z)
  487. {
  488.     return((k == 0 ? 0 : (z - point1->z3d) / k));
  489. }
  490.  
  491. void line3d::localRotate(double tX, double tY, double tZ)
  492. {
  493.     point1->localRotate(tX, tY, tZ);
  494.     point2->localRotate(tX, tY, tZ);
  495.     calcVectors();
  496. }
  497.  
  498. line3d::~line3d()
  499. {
  500.     if (flag)
  501.     {
  502.     delete point1;
  503.     delete point2;
  504.     }
  505. }
  506.  
  507.  
  508. //////
  509.    //
  510.   //    polygon class definitions
  511.  //
  512. //////
  513.  
  514. //      These are all triangles BTW
  515.  
  516. polygon::polygon()
  517. {
  518. }
  519.  
  520. polygon::polygon(point3d *v1, point3d *v2, point3d *v3, int c)
  521. {
  522.     setColor(c);
  523.     normal = new point3d;
  524.     setTo(v1, v2, v3);
  525.     shading = sNone;
  526.     facing = fBoth;
  527. }
  528.  
  529. polygon::polygon(point3d *v1, point3d *v2, point3d *v3, point3d *norm, int c)
  530. {
  531.     setColor(c);
  532.  
  533.     p1 = v1;
  534.     p2 = v2;
  535.     p3 = v3;
  536.  
  537.     normal = norm;
  538.  
  539.     line = new line3d* [3];
  540.     line[0] = new line3d(p1, p2, color);
  541.     line[1] = new line3d(p2, p3, color);
  542.     line[2] = new line3d(p3, p1, color);
  543.  
  544. }
  545.  
  546. void polygon::setTo(point3d *v1, point3d *v2, point3d *v3)
  547. {
  548.     float i, j, k, d;
  549.  
  550.     p1 = v1;
  551.     p2 = v2;
  552.     p3 = v3;
  553.  
  554.     i = (float) (((p2->localY - p1->localY) * (p3->localZ - p1->localZ)) -
  555.         ((p2->localZ - p1->localZ) * (p3->localY - p1->localY)));
  556.  
  557.     j = (float) (((p2->localZ - p1->localZ) * (p3->localX - p1->localX)) -
  558.         ((p2->localX - p1->localX) * (p3->localZ - p1->localZ)));
  559.  
  560.     k = (float) (((p2->localX - p1->localX) * (p3->localY - p1->localY)) -
  561.         ((p2->localY - p1->localY) * (p3->localX - p1->localX)));
  562.  
  563.     d = (float) sqrt((double) ((i * i) + (j * j) + (k * k)));
  564.  
  565.     i = (float) (i / d * 256);
  566.     j = (float) (j / d * 256);
  567.     k = (float) (k / d * 256);
  568.  
  569.     normal->setTo((long) i, (long) j, (long) k);
  570.     normal->copyOrigin(p1);
  571.  
  572.     line = new line3d* [3];
  573.     line[0] = new line3d(p1, p2, color);
  574.     line[1] = new line3d(p2, p3, color);
  575.     line[2] = new line3d(p3, p1, color);
  576.  
  577. }
  578.  
  579. //      average Z value of a polygon, used for depth sorting
  580.  
  581. long polygon::avgZ()
  582. {
  583.     return((long) ((p1->z3d + p2->z3d + p3->z3d) / 3));
  584. }
  585.  
  586. void polygon::setColor(int c)
  587. {
  588.     color = c;
  589. }
  590.  
  591. void polygon::wireFrame()
  592. {
  593.     for (count = 0; count < 3; count++)
  594.     line[count]->draw();
  595. }
  596.  
  597. void polygon::paintSolid()
  598. {
  599.     //dot = dotProduct(normal, camera.view);
  600.     //if (dot < 0)
  601.     if (shading)
  602.     dot = -(dotProduct(normal, camera.light));
  603.  
  604.     poly3(p1->x2d, p1->y2d, p2->x2d, p2->y2d, p3->x2d, p3->y2d,
  605.     color + (dot >> 4));
  606.  
  607.     // NOTE:  dot >> 4 = (dot / 256 * 16) = cos T * 16 = offset into
  608.     // block of 16 colors
  609.  
  610. }
  611.  
  612. void polygon::setNewOrigin(point3d *p)
  613. {
  614.     p1->setNewOrigin(p);
  615.     p2->setNewOrigin(p);
  616.     p3->setNewOrigin(p);
  617.     normal->setNewOrigin(p);
  618. }
  619.  
  620. //      this function should be called for all polygons in an object,
  621. //      following which point->avgNormals() should be called for all
  622. //      points in an object.  The obj3d->setGNormals function takes
  623. //      care of all of this...
  624.  
  625. void polygon::setGNormals()
  626. {
  627.     p1->addNormal(normal->rotoX, normal->rotoY, normal->rotoZ);
  628.     p2->addNormal(normal->rotoX, normal->rotoY, normal->rotoZ);
  629.     p3->addNormal(normal->rotoX, normal->rotoY, normal->rotoZ);
  630. }
  631.  
  632. void polygon::gShade()
  633. {
  634.     //int dot1, dot2, dot3;
  635.  
  636.     //dot = dotProduct(normal, camera.view);
  637.     //if (dot < 0)
  638.     //{
  639.     dot1 = abs(dotProduct((point3d *) p1->normal, camera.light));
  640.     dot2 = abs(dotProduct((point3d *) p2->normal, camera.light));
  641.     dot3 = abs(dotProduct((point3d *) p3->normal, camera.light));
  642.  
  643.     gzpoly3(p1->x2d, p1->y2d, p1->z3d, color + (dot1 >> 4),
  644.            p2->x2d, p2->y2d, p2->z3d, color + (dot2 >> 4),
  645.            p3->x2d, p3->y2d, p3->z3d, color + (dot3 >> 4));
  646.     //}
  647. }
  648.  
  649. void polygon::setShading(int shade)
  650. {
  651.     shading = shade;
  652. }
  653.  
  654. void polygon::setFacing(int face)
  655. {
  656.     facing = face;
  657. }
  658.  
  659. //      display a polygon according to the set shading and facing data
  660.  
  661. void polygon::display()
  662. {
  663.     if (shading)
  664.     {
  665.     if (facing)
  666.     {
  667.         dot = normal->rotoZ;
  668.         if (facing == fInside)
  669.         dot = -dot;
  670.  
  671.         if (dot < 0)
  672.         {
  673.         if (shading == sGouraud)
  674.             gShade();
  675.         else
  676.             zbFlat();
  677.         }
  678.  
  679.     }
  680.     else
  681.     {
  682.         if (shading == sGouraud)
  683.         gShade();
  684.         else
  685.         paintSolid();
  686.     }
  687.     }
  688.     else
  689.     {
  690.     if (facing)
  691.     {
  692.         dot = normal->rotoZ;
  693.         if (facing == fInside)
  694.         dot = -dot;
  695.  
  696.         if (dot < 0)
  697.         {
  698.         dot = 0;
  699.         zbFlat();
  700.         }
  701.     }
  702.     else
  703.     {
  704.         dot = 0;
  705.         zbFlat();
  706.     }
  707.     }
  708.  
  709. }
  710.  
  711. void polygon::zbFlat()
  712. {
  713.     //dot = dotProduct(normal, camera.view);
  714.     //if (dot < 0)
  715.     if (shading)
  716.     dot = -(dotProduct(normal, camera.light));
  717.  
  718.     zpoly3(p1->x2d, p1->y2d, p1->z3d, p2->x2d, p2->y2d, p2->z3d,
  719.         p3->x2d, p3->y2d, p3->z3d, color + (dot >> 4));
  720.  
  721.     // NOTE:  dot >> 11 = (dot / 256 * 16) = cos T * 16 = offset into
  722.     // block of 16 colors
  723.  
  724. }
  725.  
  726. polygon::~polygon()
  727. {
  728.     for (count = 0; count < 3; count++)
  729.     delete line[count];
  730.     delete line;
  731.     delete normal;
  732. }
  733.  
  734.  
  735. //////
  736.    //
  737.   //    obj3d class definitions
  738.  //
  739. //////
  740.  
  741.  
  742. obj3d::obj3d(long x, long y, long z)
  743. {
  744.     origin = new point3d(x, y, z);
  745.  
  746.     numPoints = 0;
  747.     numNormals = 0;
  748.     numPolys = 0;
  749.  
  750.     point = new point3d* [1];
  751.     normal = new point3d* [1];
  752.     poly = new polygon* [1];
  753.  
  754.     trig = new int [6];
  755.  
  756.     xDeg = 0;
  757.     yDeg = 0;
  758.     zDeg = 0;
  759.  
  760. }
  761.  
  762. //      the save and load functions are out of date.  If you wish, you may
  763. //      rewrite them...
  764.  
  765. void obj3d::save(FILE *fp)
  766. {
  767.     int numWritten, count2;
  768.  
  769.     polyRec *pRec = new polyRec;
  770.     objFileHeader *header = new objFileHeader;
  771.  
  772.     // assumes fp has already been opened, so we can store multiple objects
  773.     // in the same file
  774.  
  775.     header->numPoints = numPoints;
  776.     header->numPolys = numPolys;
  777.  
  778.     numWritten = fwrite(header, sizeof(objFileHeader), 1, fp);
  779.  
  780.     for (count = 0; count < numPoints; count++)
  781.     point[count]->save(fp);
  782.  
  783.     for (count2 = 0; count2 < numPolys; count2++)
  784.     {
  785.     pRec->p1 = getPointNum(poly[count2]->p1);
  786.     pRec->p2 = getPointNum(poly[count2]->p2);
  787.     pRec->p3 = getPointNum(poly[count2]->p3);
  788.     pRec->normal = getPointNum(poly[count2]->normal);
  789.     pRec->color = poly[count2]->color;
  790.  
  791.     numWritten = fwrite(pRec, sizeof(polyRec), 1, fp);
  792.  
  793.     }
  794.  
  795. }
  796.  
  797. void obj3d::load(FILE *fp)
  798. {
  799.     int numRead;
  800.  
  801.     polyRec *pRec = new polyRec;
  802.     objFileHeader *header = new objFileHeader;
  803.  
  804.     // free old data
  805.  
  806.     for (count = 0; count < numPoints; count++)
  807.     delete point[count];
  808.  
  809.     for (count = 0; count < numPolys; count++)
  810.     delete point[count];
  811.  
  812.     // assumes fp has already been opened, so we can store multiple objects
  813.     // in the same file
  814.  
  815.     numRead = fread(header, sizeof(objFileHeader), 1, fp);
  816.  
  817.     numPoints = header->numPoints;
  818.     numPolys = header->numPolys;
  819.  
  820.     for (count = 0; count < numPoints; count++)
  821.     {
  822.     point[count] = new point3d;
  823.     point[count]->load(fp);
  824.     point[count]->globalXform2origin(origin);
  825.     }
  826.  
  827.     for (count = 0; count < numPolys; count++)
  828.     {
  829.     numRead = fread(pRec, sizeof(polyRec), 1, fp);
  830.  
  831.     poly[count] = new polygon(point[pRec->p1], point[pRec->p2],
  832.         point[pRec->p3], point[pRec->normal], pRec->color);
  833.     }
  834.  
  835.     // nix the old rotations...
  836.  
  837.     xDeg = 0;
  838.     yDeg = 0;
  839.     zDeg = 0;
  840. }
  841.  
  842. //      add a point whose coordinates are given as local to the origin of
  843. //      this object to this objects list of points
  844.  
  845. void obj3d::addLocalPoint(long x, long y, long z)
  846. {
  847.     point3d **temp;
  848.  
  849.     temp = new point3d* [numPoints + 1];
  850.     memcpy(temp, point, numPoints * sizeof(point3d*));
  851.  
  852.     delete point;
  853.     point = temp;
  854.  
  855.     numPoints++;
  856.     point[numPoints - 1] = new point3d(x, y, z);
  857.     point[numPoints - 1]->globalXform2origin(origin);
  858.  
  859. }
  860.  
  861. void obj3d::addNormal(long x, long y, long z)
  862. {
  863.     point3d **temp;
  864.  
  865.     temp = new point3d* [numNormals + 1];
  866.     memcpy(temp, normal, numNormals * sizeof(point3d*));
  867.  
  868.     delete normal;
  869.     normal = temp;
  870.  
  871.     numNormals++;
  872.     normal[numNormals - 1] = new point3d(x, y, z);
  873.     normal[numNormals - 1]->globalXform2origin(origin);
  874.  
  875. }
  876.  
  877. void obj3d::addLocalPoint(point3d *p)
  878. {
  879.     point3d **temp;
  880.  
  881.     temp = new point3d* [numPoints + 1];
  882.     memcpy(temp, point, numPoints * sizeof(point3d*));
  883.  
  884.     delete point;
  885.     point = temp;
  886.  
  887.     p->globalXform2origin(origin);
  888.     numPoints++;
  889.     point[numPoints - 1] = p;
  890. }
  891.  
  892. void obj3d::addNormal(point3d *p)
  893. {
  894.     point3d **temp;
  895.  
  896.     temp = new point3d* [numNormals + 1];
  897.     memcpy(temp, normal, numNormals * sizeof(point3d*));
  898.  
  899.     delete normal;
  900.     normal = temp;
  901.  
  902.     p->globalXform2origin(origin);
  903.     numNormals++;
  904.     normal[numNormals - 1] = p;
  905. }
  906.  
  907. //      add a point whose coordinates are given in terms of THE (0,0,0)
  908. //      origin to this object's list of points
  909.  
  910. void obj3d::addGlobalPoint(long x, long y, long z)
  911. {
  912.     addLocalPoint(x - origin->x3d, y - origin->y3d, z - origin->z3d);
  913. }
  914.  
  915. void obj3d::addGlobalPoint(point3d *p)
  916. {
  917.     p->setNewOrigin(origin);
  918.     addLocalPoint(p);
  919. }
  920.  
  921. //      add a local polygon (whose vertices are local points)
  922.  
  923. void obj3d::addLocalPoly(polygon *pg)
  924. {
  925.     polygon **temp;
  926.  
  927.     temp = new polygon* [numPolys + 1];
  928.     memcpy(temp, poly, numPolys * sizeof(polygon*));
  929.  
  930.     delete poly;
  931.     poly = temp;
  932.  
  933.     numPolys++;
  934.     poly[numPolys - 1] = pg;
  935.     addNormal(pg->normal);
  936. }
  937.  
  938. void obj3d::addLocalPoly(int p1, int p2, int p3, int c)
  939. {
  940.     polygon *pg = new polygon(point[p1], point[p2], point[p3], c);
  941.     addLocalPoly(pg);
  942. }
  943.  
  944. //      add a poly whose vertices are given in global coordinates
  945.  
  946. void obj3d::addGlobalPoly(polygon *pg)
  947. {
  948.     pg->setNewOrigin(origin);
  949.     addLocalPoly(pg);
  950. }
  951.  
  952. int obj3d::getPointNum(long x, long y, long z)
  953. {
  954.     for (count = 0; count < numPoints; count++)
  955.        if (point[count]->localX == x && point[count]->localY == y &&
  956.         point[count]->localZ == z)
  957.         return(count);
  958.  
  959.     // couldn't find it, let's CREATE IT!
  960.     addLocalPoint(x, y, z);
  961.     return(numPoints - 1);
  962. }
  963.  
  964. int obj3d::getPointNum(point3d *p)
  965. {
  966.     for (count = 0; count < numPoints; count++)
  967.     if (point[count] == p)
  968.         return(count);
  969.  
  970.     return(-1);
  971. }
  972.  
  973. //      rotate this object about it's origin
  974.  
  975. void obj3d::localRotate(int tX, int tY, int tZ)
  976. {
  977.     xDeg += tX;
  978.     yDeg += tY;
  979.     zDeg += tZ;
  980.  
  981.     xDeg %= 360;
  982.     yDeg %= 360;
  983.     zDeg %= 360;
  984.  
  985.     trig[0] = zDSin(xDeg);
  986.     trig[1] = zDCos(xDeg);
  987.     trig[2] = zDSin(yDeg);
  988.     trig[3] = zDCos(yDeg);
  989.     trig[4] = zDSin(zDeg);
  990.     trig[5] = zDCos(zDeg);
  991.  
  992.     for (count = 0; count < numPoints; count++)
  993.     {
  994.         point[count]->localRotate(trig);
  995.         point[count]->xform2d();
  996.     }
  997.  
  998.     for (count = 0; count < numNormals; count++)
  999.         normal[count]->localRotate(trig);
  1000. }
  1001.  
  1002. void obj3d::matRotate(int tX, int tY, int tZ)
  1003. {
  1004.     int cx, cy, cz, sx, sy, sz;
  1005.  
  1006.     // 0 1 2
  1007.     // 3 4 5
  1008.     // 6 7 8
  1009.  
  1010.     xDeg += tX;
  1011.     yDeg += tY;
  1012.     zDeg += tZ;
  1013.  
  1014.     xDeg %= 360;
  1015.     yDeg %= 360;
  1016.     zDeg %= 360;
  1017.  
  1018.     //cx = cos((double) xDeg * PI / 180);
  1019.     //sx = sin((double) xDeg * PI / 180);
  1020.     //cy = cos((double) yDeg * PI / 180);
  1021.     //sy = sin((double) yDeg * PI / 180);
  1022.     //cz = cos((double) zDeg * PI / 180);
  1023.     //sz = sin((double) zDeg * PI / 180);
  1024.  
  1025.     sx = zDSin(xDeg);
  1026.     cx = zDCos(xDeg);
  1027.     sy = zDSin(yDeg);
  1028.     cy = zDCos(yDeg);
  1029.     sz = zDSin(zDeg);
  1030.     cz = zDCos(zDeg);
  1031.  
  1032.     matrix[0] = ((cz * cy) << SINSHIFT ) + (((sx * sz) ) * sy) ;
  1033.     matrix[1] = ((-sz * cy) << SINSHIFT ) + (((sx * cz) ) * sy) ;
  1034.     matrix[2] = (cx * sy) << SINSHIFT;
  1035.     matrix[3] = (cx * sz) << SINSHIFT;
  1036.     matrix[4] = (cx * cz) << SINSHIFT;
  1037.     matrix[5] = -sx << (2 * SINSHIFT);
  1038.     matrix[6] = ((-cz * sy) << SINSHIFT) + (((sx * sz) ) * cy) ;
  1039.     matrix[7] = ((sz * sy) << SINSHIFT) + (((sx * cz) ) * cy) ;
  1040.     matrix[8] = (cx * cy) << SINSHIFT;
  1041.  
  1042.     matrix[0] >>= 16;
  1043.     matrix[1] >>= 16;
  1044.     matrix[2] >>= 16;
  1045.     matrix[3] >>= 16;
  1046.     matrix[4] >>= 16;
  1047.     matrix[5] >>= 16;
  1048.     matrix[6] >>= 16;
  1049.     matrix[7] >>= 16;
  1050.     matrix[8] >>= 16;
  1051.  
  1052.     for (count = 0; count < numPoints; count++)
  1053.     {
  1054.         point[count]->matRotate();
  1055.         point[count]->xform2d();
  1056.     }
  1057.  
  1058.     for (count = 0; count < numNormals; count++)
  1059.         normal[count]->matRotate();
  1060. }
  1061.  
  1062.  
  1063. /*
  1064. void obj3d::localRotate(int dTheta, int dPhi)
  1065. {
  1066.     for (count = 0; count < numPoints; count++)
  1067.     point[count]->localRotate(dTheta, dPhi);
  1068. }
  1069. */
  1070.  
  1071. //      translate (move) this object
  1072.  
  1073. void obj3d::translate(int dX, int dY, int dZ)
  1074. {
  1075.     origin->translate(dX, dY, dZ);
  1076.     for (count = 0; count < numPoints; count++)
  1077.     {
  1078.         point[count]->translate(dX, dY, dZ);
  1079.         point[count]->xform2d();
  1080.     }
  1081.  
  1082.     for (count = 0; count < numNormals; count++)
  1083.         normal[count]->translate(dX, dY, dZ);
  1084. }
  1085.  
  1086. //      rotate this object about THE (0,0,0) origin
  1087.  
  1088. void obj3d::globalRotate(int *trig)
  1089. {
  1090.     origin->globalRotate(trig);
  1091.     for (count  = 0; count < numPoints; count++)
  1092.     {
  1093.         point[count]->globalRotate(trig);
  1094.         point[count]->xform2d();
  1095.     }
  1096.  
  1097.     for (count = 0; count < numNormals; count++)
  1098.         normal[count]->globalRotate(trig);
  1099. }
  1100.  
  1101. //      depth sort this object's planes
  1102.  
  1103. void obj3d::sortPlanes()
  1104. {
  1105.     polygon *temp;
  1106.     register int pos, index;
  1107.  
  1108.     for (pos = 0; pos < (numPolys - 1); pos++)
  1109.     {
  1110.     index = pos;
  1111.     for (count = index + 1; count < numPolys; count++)
  1112.         if (poly[count]->avgZ() > poly[index]->avgZ())
  1113.         index = count;
  1114.  
  1115.     if (index != pos)
  1116.     {
  1117.         temp = poly[pos];
  1118.         poly[pos] = poly[index];
  1119.         poly[index] = temp;
  1120.     }
  1121.     }
  1122.  
  1123. }
  1124.  
  1125. //      display as dots
  1126.  
  1127. void obj3d::paintDots()
  1128. {
  1129.     for (count = 0; count < numPoints; count++)
  1130.     point[count]->display(15);
  1131. }
  1132.  
  1133. //      display as a wireframe
  1134.  
  1135. void obj3d::wireFrame()
  1136. {
  1137.     sortPlanes();
  1138.     for (count = 0; count < numPolys; count++)
  1139.     poly[count]->wireFrame();
  1140. }
  1141.  
  1142. //      display Lambert (flat) shaded
  1143.  
  1144. void obj3d::paintSolid()
  1145. {
  1146.     sortPlanes();
  1147.     for (count = 0; count < numPolys; count++)
  1148.     poly[count]->paintSolid();
  1149. }
  1150.  
  1151. //      set the location of this object in global coordinates
  1152.  
  1153. void obj3d::setLocation(long x, long y, long z)
  1154. {
  1155.     origin->setTo(x, y, z);
  1156.     for (count = 0; count < numPoints; count++)
  1157.     point[count]->setNewOrigin(origin);
  1158. }
  1159.  
  1160. //      have this object set up its normal vectors needed for gouraud shading
  1161.  
  1162. void obj3d::setGNormals()
  1163. {
  1164.     int temp;
  1165.  
  1166.     for (count = 0; count < numPolys; count++)
  1167.         poly[count]->setGNormals();
  1168.  
  1169.     for (count = 0; count < numPoints; count++)
  1170.         point[count]->avgNormal();
  1171.  
  1172.     temp = numPoints;
  1173.     for (count = 0; count < temp; count++)
  1174.     if (point[count]->nCount)
  1175.     {
  1176.         addNormal(point[count]->nX, point[count]->nY, point[count]->nZ);
  1177.         point[count]->normal = (void *) normal[numNormals - 1];
  1178.     }
  1179.  
  1180. }
  1181.  
  1182. //      gouraud shade this object
  1183.  
  1184. void obj3d::gShade()
  1185. {
  1186.     sortPlanes();
  1187.     for (count = 0; count < numPolys; count++)
  1188.     poly[count]->gShade();
  1189.  
  1190. }
  1191.  
  1192. //      universal display function that utilizes each polygon's shading
  1193. //      and facing data.  This allows you to combine gouraud, flat, and
  1194. //      nonshaded polygons in the same object.
  1195.  
  1196. void obj3d::display()
  1197. {
  1198.     //sortPlanes();
  1199.     for (count = 0; count < numPolys; count++)
  1200.         poly[count]->display();
  1201. }
  1202.  
  1203. void obj3d::zbFlat()
  1204. {
  1205.     for (count = 0; count < numPolys; count++)
  1206.         poly[count]->display();
  1207. }
  1208.  
  1209. obj3d::~obj3d()
  1210. {
  1211.     for (count = 0; count < numPolys; count++)
  1212.         delete poly[count];
  1213.  
  1214.     for (count = 0; count < numNormals; count++)
  1215.         delete normal[count];
  1216.  
  1217.     for (count = 0; count < numPoints; count++)
  1218.         delete point[count];
  1219.  
  1220.     delete trig;
  1221.     delete poly;
  1222.     delete point;
  1223.     delete origin;
  1224. }
  1225.  
  1226.  
  1227. //      THE WORLD AND VIEWPOINT CLASSES HAVE NOT BEEN FULLY IMPLEMENTED!  If
  1228. //      you want to use them, rewrite them.  You MUST leave the light and view
  1229. //      vectors in the camera class, though.  They are used for shading and
  1230. //      plane elimination
  1231.  
  1232. //////
  1233.    //
  1234.   //    world3d class definitons
  1235.  //
  1236. //////
  1237.  
  1238.  
  1239. world3d::world3d()
  1240. {
  1241.     object = new obj3d* [MAX_OBJS];
  1242.     numObjs = 0;
  1243.     initSinCos();
  1244.     initPerspect();
  1245. }
  1246.  
  1247. world3d::~world3d()
  1248. {
  1249.     int count;
  1250.  
  1251.     delPerspect();
  1252.     for (count = 0; count < numObjs; count++)
  1253.         delete object[count];
  1254.  
  1255.     delete object;
  1256. }
  1257.  
  1258.  
  1259. //////
  1260.    //
  1261.   //    viewPoint class definitions
  1262.  //
  1263. //////
  1264.  
  1265.  
  1266. viewPoint::viewPoint()
  1267. {
  1268.     location = new point3d(0, 0, 0);
  1269.     light = new point3d(0, 0, 1);
  1270.     view = new point3d(0, 0, 1);
  1271. }
  1272.  
  1273. viewPoint::~viewPoint()
  1274. {
  1275.     delete location;
  1276.     delete light;
  1277.     delete view;
  1278. }
  1279.  
  1280.